#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
// #include <pcap.h>
#include <time.h>
#include <sys/resource.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <linux/if_ether.h>
// #include <pcap-int.h>
#include <sys/epoll.h> 
#include <fcntl.h>
#include <errno.h>
#include <netpacket/packet.h>
#include <net/if_arp.h>

#define MAXEPOLLSIZE 10000
//#define DEBUG_LINK

#ifdef DEBUG_LINK
    #define    PRINTF    printf
    #define    FPRINTF   fprintf
#else
    #define    PRINTF
    #define    FPRINTF
#endif


enum PACKET_TYPE {
    PT_COMMAND,
    PT_RESPONSE,
    PT_LINKPACKET
};

struct packet_header {
    int pack_length;
    int ph_type;
    int ph_length;
    int ph_num;
    u_char ph_data[];
};

int getIfaceIndex(int fd, const char* interfaceName);
int setMacAddr(char *addr);
int setMembership(int add, int fd, unsigned short addr_len, unsigned char *addr);
int setPromisc(int fd, int type);

static  int             g_connectionFD = -1;
static  char            g_ethname[20];
static  int             g_captureFD;
// static  pcap_t*         g_pcapHandle = NULL;
static  pthread_t       g_captureThreadID;
static  struct ifreq    ifr;
static  struct sockaddr send_addr;

#define READ_BUFFER_LEN (1024)
#define RING_BUFFER_LEN	(1024 * 10)
#define	RECV_BUFFER_LEN (2048)



/*****************************************
*parse IGMP set MAC add Multicast
*
*
******************************************/
int parseIGMP(u_char *packet, int len)
{
	u_char multicast_addr[6] = {0};
	u_char src_addr[6] = {0};
	u_char *p = packet;
	int IGMPver = 0;
	int ip_head_len;
	int ip_len = 0;
	int record_num = 0;
	int i;

	//printf("len = %d \n");
	if (!p)
		return -1;

	if (len > 12) {
		memcpy(multicast_addr, p, 6);
		memcpy(src_addr, p + 6, 6);
	}
	p += 12;


	if (len > 14) {
		if (ntohs(*(u_short*)p) == 0x0800) {
			//printf("ip\n");
			p += 2;
		}
	}

	//ip packet
	if (len > 15) {
		ip_head_len = (*p & 0x0f) * 4;
		//printf("ip_head_len = %d \n", ip_head_len);
		if (len > 14 + ip_head_len) {
			if (*(p + 9) != 2) {
				return 0;
			}
			printf("IGMP \n");
		
			p += ip_head_len;

			//IGMP ver1/2
			printf("0x%x ..... \n", *p);
		    if ((*p == 0x12) //ver1
			  ||(*p == 0x16)){//ver2 
			  p += 4;
			  
			  multicast_addr[0] = 0x01;
			  multicast_addr[1] = 0x00;
			  multicast_addr[2] = 0x5e;
			  multicast_addr[3] = (*(p + 1)) & 0x7f;
			  multicast_addr[4] = *(p + 2);
			  multicast_addr[5] = *(p + 3);
			  
				setMacAddr((char *)src_addr);
						for (i = 0; i < 6; i++) {
		    				printf("0x%x, ", multicast_addr[i]);
	    				}

	    				printf("\n");
				setMembership(1, g_captureFD, 6, (unsigned char *)multicast_addr);
				
			} else if (*p == 0x17){//ver2
				//setMacAddr(src_addr);
				p += 4;
				multicast_addr[0] = 0x01;
				multicast_addr[1] = 0x00;
				multicast_addr[2] = 0x5e;
				multicast_addr[3] = (*(p + 1)) & 0x7f;
				multicast_addr[4] = *(p + 2);
				multicast_addr[5] = *(p + 3);
				
						for (i = 0; i < 6; i++) {
		    				printf("0x%x, ", multicast_addr[i]);
	    				}

	    				printf("\n");
				setMembership(0, g_captureFD, 6, (unsigned char *)multicast_addr);
			}			

			//IGMP ver3
			if ((*p == 0x22) && (len > 14 + ip_head_len + 8)) {
				record_num = (ntohs)(*(u_short *)(p + 6));
				printf("record_num = %d \n", record_num);
				p += 8;
				for (i = 0; i < record_num; i++) {
					
					multicast_addr[0] = 0x01;
					multicast_addr[1] = 0x00;
					multicast_addr[2] = 0x5e;
					multicast_addr[3] = (*(p + 5)) & 0x7f;
					multicast_addr[4] = *(p + 6);
					multicast_addr[5] = *(p + 7);
					if (*p == 1 || *p == 3) {
						int j;
						setMacAddr((char *)src_addr);
						setMembership(0, g_captureFD, 6, (unsigned char *)multicast_addr);
						
						for (j = 0; j < 6; j++) {
		    				printf("0x%x, ", multicast_addr[j]);
	    				}

	    				printf("\n");
					}

					if (*p == 2 || *p == 4) {
						int j;
						setMacAddr((char *)src_addr);
						setMembership(1, g_captureFD, 6, (unsigned char *)multicast_addr);			
                        
						for (j = 0; j < 6; j++) {
		    				printf("0x%x, ", multicast_addr[j]);
	    				}

	    				printf("\n");
					}

					p += 8;
				}
			}	

		}
	}

	
	
}


/*****************************************
*set MAC addr
*
*
******************************************/
int setMacAddr(char *addr)
{
    struct ifreq ifr;

    ifr.ifr_addr.sa_family = ARPHRD_ETHER;
    memcpy(ifr.ifr_name, g_ethname, strlen(g_ethname) + 1);
    memcpy(&ifr.ifr_hwaddr.sa_data, addr, 6);

	printf("set mac %s \n", g_ethname);
    if (ioctl(g_captureFD, SIOCSIFHWADDR, &ifr) != 0) {
        printf("set mac error!\n");
        return -1;
    }

    return 0;
}


/*****************************************
*add /drop multicast
*param:
*      add == 1 add Mulitcast, == 0 drop Multicast
*
******************************************/
int setMembership(int add, int fd, unsigned short addr_len, unsigned char *addr)
{
    struct packet_mreq mr;
    bzero(&mr, sizeof(mr));

    mr.mr_ifindex   = getIfaceIndex(fd, g_ethname);
    mr.mr_type      = PACKET_MR_MULTICAST;//if_packet.h
    mr.mr_alen      = addr_len;
    memcpy(mr.mr_address, addr, addr_len);

    if (add == 1) {
        if (setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mr, sizeof(mr)) == -1) {
            printf("%d error \n", __LINE__);
            return -1;
        }
		printf("join multicast \n");
    } else if (add == 0){
        if (setsockopt(fd, SOL_PACKET, PACKET_DROP_MEMBERSHIP, &mr, sizeof(mr)) == -1) {
            printf("%d error \n", __LINE__);
            return -1;
        }
		printf("leave multicast \n");
    }

    return 0;
}


/*****************************************
*type == 1 set promisc
*type == 0 set no promisc
*
*
******************************************/
int setPromisc(int fd, int type)
{
    int ret = 0;
    struct ifreq ifr;
    int listen_fd;
    
    memcpy(ifr.ifr_name, g_ethname, strlen(g_ethname) + 1);

    PRINTF("type = %d \n", type);
    if ((ret = ioctl(fd, SIOCGIFFLAGS, &ifr)) < 0) {
        PRINTF("%d error\n", __LINE__);
        return -1;
    }

    if (type == 1)
        ifr.ifr_flags |= IFF_PROMISC;
    else
        ifr.ifr_flags &= (~IFF_PROMISC);
    
    if ((ret = ioctl(fd, SIOCSIFFLAGS, &ifr)) < 0) {
        PRINTF("%d error \n", __LINE__);
        return -1;
    }
    return 0;
}


/*****************************************
*get Interface Id from Interface Name
*
*
*
******************************************/
int getIfaceIndex(int fd, const char* interfaceName)
{
    struct ifreq ifr;
    memset(&ifr, 0, sizeof(ifr));
    
    if (interfaceName == NULL)
    {
        return -1;
    }
    
    strcpy(ifr.ifr_name, interfaceName);

    if (ioctl(fd, SIOCGIFINDEX, &ifr) == -1)
    {
        PRINTF("RED ioctl error\n");
        return -1;
    }
    return ifr.ifr_ifindex;
}


#if 0
static void* captureThread(void*)
{
    struct packet_header *send_packet = NULL;
    int res = 0;
    int num = 0;
    int packet_len = 0;
    char rcv_buf[RECV_BUFFER_LEN] = {0};

    /* Retrieve the packets */  
    while ((res = recvfrom(g_captureFD, rcv_buf, RECV_BUFFER_LEN, 0, NULL, NULL)) > 0 ) {      
        PRINTF("cap size : %d \n", res);
        
        packet_len  = (sizeof(struct packet_header) + res + 3) & (~0x03);
        send_packet = (struct packet_header *)malloc(packet_len);
        memset(send_packet, 0, packet_len);

        send_packet->pack_length = packet_len;
        send_packet->ph_type     = PT_LINKPACKET;
        send_packet->ph_length   = res;
        send_packet->ph_num      = num++;
        memcpy(send_packet->ph_data, rcv_buf, res);
    
        res = send(g_connectionFD, send_packet, packet_len, 0);
        if (res == packet_len)           
            PRINTF("%d &&send&&  %d bytes...... \n", send_packet->ph_num, res);

        free(send_packet);
        send_packet = NULL;
        
    }
     
   return 0;
}
#endif


static int doCommandServer(char* buffer, int length)
{
    int send_len   = 0;
    int packet_len = 0;
    struct packet_header *send_packet = NULL;
    
    if (buffer == NULL || length < 0)
        return -1;

    length += 1;
    buffer[length] = '\0';
    PRINTF("Server receive stdin command: %d %s\n", length, buffer);

    packet_len  = (sizeof(struct packet_header) + length + 3) & (~0x03);
    send_packet = (struct packet_header *)malloc(packet_len);

    send_packet->pack_length = packet_len;
    send_packet->ph_type     = PT_COMMAND;
    send_packet->ph_length   = length;
    send_packet->ph_num      = 0;
    
    memcpy(send_packet->ph_data, buffer, length);

    send_len = send(g_connectionFD, send_packet, packet_len, 0);

    free(send_packet);
    send_packet = NULL;
    
    if (send_len == packet_len) {
        PRINTF("send cmd ok...\n");
    }
    else
        return -1;

    return 0;
}

static int doRequestServer(char *pCommand, int cmd_len)
{
    FILE *fstream         = NULL;
    int   packet_len      = 0;
    int   send_len        = 0;
    char  temp_buff[READ_BUFFER_LEN]  = {0};
    char  error_info[]    = "execute command fail!\n";
    struct packet_header *send_packet = NULL;
    
    bzero(temp_buff, READ_BUFFER_LEN);
    memcpy(temp_buff, pCommand, READ_BUFFER_LEN);

    packet_len  = sizeof(struct packet_header) + READ_BUFFER_LEN;
    send_packet = (struct packet_header *)malloc(packet_len);

    send_packet->pack_length = packet_len;
    send_packet->ph_type     = PT_RESPONSE;
    send_packet->ph_length   = READ_BUFFER_LEN;
    send_packet->ph_num      = 0;

    bzero(send_packet->ph_data, READ_BUFFER_LEN);
    
    //exec cmd
    if ((strncmp(temp_buff, "promisc", strlen("promisc"))) == 0) {
        //set promisc
        PRINTF("in promisc\n");
        setPromisc(g_captureFD, 1);
        
    } else if ((strncmp(temp_buff, "-promisc", strlen("-promisc"))) == 0) {
        //set no promisc
        PRINTF("in nopromisc\n");
        setPromisc(g_captureFD, 0);
        
    } else if (NULL == (fstream = popen(temp_buff, "r"))) {
        memcpy(send_packet->ph_data, error_info, sizeof(error_info));
        send_len = send(g_connectionFD, send_packet, packet_len, 0);
        if (send_len == packet_len) {
            PRINTF("cmd response ok!\n");
        }
    } else {
        //strcpy(temp_buff, "***************************");
        memcpy(send_packet->ph_data, "\n**************************************\n",40);
        send_len = send(g_connectionFD, send_packet, packet_len, 0);
        //send the response info
        while (NULL != fgets(temp_buff, READ_BUFFER_LEN, fstream)) {
            memcpy(send_packet->ph_data, temp_buff, 1024);
        
            send_len = send(g_connectionFD, send_packet, packet_len, 0);
            if (send_len == packet_len) {
                PRINTF("cmd response ok!\n");
            }
        }
        bzero(send_packet->ph_data, READ_BUFFER_LEN);
        memcpy(send_packet->ph_data, "**************************************\n\n",40);
        send_len = send(g_connectionFD, send_packet, packet_len, 0);
    }
    
    free(send_packet);
    send_packet = NULL;

    return 0;
}

static int doCommandClient(char* buffer, int length)
{
    int send_len   = 0;
    int packet_len = 0;
    struct packet_header *send_packet = NULL;
    
    if (buffer == NULL || length < 0)
        return -1;

    length += 1;
    buffer[length] = '\0';
    PRINTF("Client receive stdin command: %d %s\n", length, buffer);

    packet_len  = (sizeof(struct packet_header) + length + 3) & (~0x03);
    send_packet = (struct packet_header *)malloc(packet_len);

    send_packet->pack_length = packet_len;
    send_packet->ph_type     = PT_COMMAND;
    send_packet->ph_length   = length;
    send_packet->ph_num      = 0;
    
    memcpy(send_packet->ph_data, buffer, length);

    send_len = send(g_connectionFD, send_packet, packet_len, 0);

    free(send_packet);
    send_packet = NULL;
    
    if (send_len == packet_len) {
        PRINTF("send cmd ok... \n");
    }
    else
        return -1;

    return 0;
}

static int doRequestClient(char *pCommand, int cmd_len)
{
    FILE *fstream         = NULL;
    int   packet_len      = 0;
    int   send_len        = 0;
    char  temp_buff[READ_BUFFER_LEN]  = {0};
    char  error_info[]    = "execute command fail!\n";
    struct packet_header *send_packet = NULL;
    
    bzero(temp_buff, READ_BUFFER_LEN);
    memcpy(temp_buff, pCommand, READ_BUFFER_LEN);

    packet_len  = sizeof(struct packet_header) + READ_BUFFER_LEN;
    send_packet = (struct packet_header *)malloc(packet_len);

    send_packet->pack_length = packet_len;
    send_packet->ph_type     = PT_RESPONSE;
    send_packet->ph_length   = READ_BUFFER_LEN;
    send_packet->ph_num      = 0;

    bzero(send_packet->ph_data, READ_BUFFER_LEN);
    
    
    //exec cmd
    if ((strncmp(temp_buff, "promisc", 7)) == 0) {
        //set promisc
        PRINTF("in promisc\n");
        setPromisc(g_captureFD, 1);
        
    } else if ((strncmp(temp_buff, "-promisc", 8)) == 0) {
        //set no promisc
        PRINTF("in nopromisc\n");
        setPromisc(g_captureFD, 0);
        
    } else if (NULL == (fstream = popen(temp_buff, "r"))) {
        //FPRINTF(stderr, error_info);
        memcpy(send_packet->ph_data, error_info, sizeof(error_info));
        send_len = send(g_connectionFD, send_packet, packet_len, 0);
        if (send_len == packet_len) {
            PRINTF("cmd response ok!\n");
        }
    } else {
        //strcpy(temp_buff, "***************************");
        memcpy(send_packet->ph_data, "\n**************************************\n",40);
        send_len = send(g_connectionFD, send_packet, packet_len, 0);
        //send the response info
        while (NULL != fgets(temp_buff, READ_BUFFER_LEN, fstream)) {
            memcpy(send_packet->ph_data, temp_buff, 1024);
        
            send_len = send(g_connectionFD, send_packet, packet_len, 0);
            if (send_len == packet_len) {
                PRINTF("cmd response ok!\n");
            }
        }
        bzero(send_packet->ph_data, READ_BUFFER_LEN);
        memcpy(send_packet->ph_data, "**************************************\n\n",40);
        send_len = send(g_connectionFD, send_packet, packet_len, 0);
    }
    
    free(send_packet);
    send_packet = NULL;

    return 0;

}


static void* dealReceiveData(int (*doCommand)(char*, int), int (*doRequest)(char *, int))
{
    fd_set      rset;
    int         rest_len      = 0;
    int         recv_len      = 0;
    int         temp_len      = 0;
    int            head_len      = sizeof(struct packet_header);
    int         ret           = 0;
    int         i             = 0;
    int         packet_length = 0;
    int         packet_type   = -1;
    int            max_fd          = 0;
    u_char     *write_pos     = NULL;
    u_char     *read_pos      = NULL;
    u_char     *ring_buf      = NULL;
    u_char     *data          = NULL;
    u_char     *start_pos     = NULL;
    u_char     *end_pos       = NULL;
    u_char     *read_buf      = NULL;
    char       *rcv_buf       = NULL;
    ring_buf    = (u_char *)malloc(RING_BUFFER_LEN);
    read_buf     = (u_char *)malloc(READ_BUFFER_LEN);
    rcv_buf     = (char *)malloc(RECV_BUFFER_LEN);
    read_pos    = ring_buf + 1600; //
    write_pos    = ring_buf + 1600; //
    end_pos     = ring_buf + RING_BUFFER_LEN;
    start_pos    = ring_buf + 1600; //
    max_fd        = ((g_captureFD < g_connectionFD) ? g_connectionFD : g_captureFD);
    bzero(ring_buf, RING_BUFFER_LEN);
    bzero(read_buf, READ_BUFFER_LEN);
    bzero(rcv_buf, RECV_BUFFER_LEN);
    struct packet_header *send_packet = NULL;
    int num = 0;
    int packet_len = 0;
    
    while (1) {
        FD_ZERO(&rset);
        FD_SET(0, &rset);
        FD_SET(g_connectionFD, &rset);
        FD_SET(g_captureFD, &rset);

        if ((ret = select(max_fd + 1, &rset, NULL, NULL, NULL)) < 0)
            return NULL;

        //CMD read
        if (FD_ISSET(0, &rset)) {
            memset(read_buf, 0, READ_BUFFER_LEN);
            recv_len = read(0, read_buf, READ_BUFFER_LEN);
            if (recv_len <= 0)
                break;
    
            doCommand((char*)read_buf, recv_len);
        }

        //TCP recv
        if (FD_ISSET(g_connectionFD, &rset)) {
            if (write_pos == end_pos)
                write_pos = start_pos;
             
            if (write_pos >= read_pos)
                recv_len = recv(g_connectionFD, write_pos, (end_pos - write_pos), 0);   
            else
                recv_len = recv(g_connectionFD, write_pos, ((read_pos - 1) - write_pos), 0);

            if (recv_len <= 0)
                break;

            // PRINTF("===============recv_len = %d============= \n", recv_len);
            
            write_pos += recv_len;
            // PRINTF("=============write_pos = %d ========== \n", write_pos - start_pos);        
    
            rest_len += recv_len;
            
            // PRINTF("===============rest_len = %d============= \n", rest_len);

            while (1) {
                if (rest_len < head_len)
                    break;

                //move the last bytes to begin pos
                if ((end_pos - read_pos) < 1600) {
                    if (write_pos >= read_pos) {
                        memcpy((ring_buf + (1600 - (write_pos - read_pos))), read_pos, (write_pos - read_pos));
                        read_pos = ring_buf + (1600 - (write_pos - read_pos));
                        write_pos = start_pos;
                    }else {
                        if (packet_length > 1520)
                            printf("packet len: %d\n", packet_length);
                        memcpy((ring_buf + (1600 - (end_pos - read_pos))), read_pos, (end_pos - read_pos));
                        read_pos = ring_buf + (1600 - (end_pos - read_pos));
                    }
                }
                                
                packet_length = ((struct packet_header *)read_pos)->pack_length;
                packet_type   = ((struct packet_header *)read_pos)->ph_type;
                // PRINTF("=============== packet_length = %d =============\n", packet_length);
                
                //not recv complete packet
                if (packet_length <= 0 || packet_length > rest_len)
                    break;


                //length too long
                temp_len = ((struct packet_header *)read_pos)->ph_length;
                if (temp_len > 1514) {
                    temp_len = 1514;
                }        
             
                //send packet
                if (packet_type == PT_LINKPACKET) {
                    PRINTF("0x%x, 0x%x, 0x%x \n", g_captureFD, ((struct packet_header *)read_pos)->ph_data, temp_len);

                    //parse if IGMP
                    //parseIGMP(((struct packet_header *)read_pos)->ph_data, temp_len);
					if (send(g_captureFD, ((struct packet_header *)read_pos)->ph_data, temp_len, 0) < 0) {
                        PRINTF("%d send packet error! \n", __LINE__);
                        return NULL;
                    }
                    else
                        PRINTF("pcap_sendpacket OK\n");
                    
                } else if (packet_type == PT_COMMAND) {
                    //exec CMD
                    doRequest((char *)(((struct packet_header *)read_pos)->ph_data), temp_len);
                    
                } else if (packet_type == PT_RESPONSE) {
                    //echo the response info
                    fputs((const char *)(((struct packet_header *)read_pos)->ph_data), stdout);
                }
            
                //move the read pos
                read_pos += packet_length;

                //the rest bytes to read
                rest_len -= packet_length;
                }
            }

            //Capture recv
            if (FD_ISSET(g_captureFD, &rset)) {
                if ((ret = recvfrom(g_captureFD, rcv_buf, RECV_BUFFER_LEN, 0, NULL, NULL)) > 0 ) {        
                    PRINTF("cap size : %d \n", ret);
                    if (ret > 1520) {
                        //printf("error ret: %d\n", ret);
                        continue;
                    }
                    packet_len  = (sizeof(struct packet_header) + ret + 3) & (~0x03);
                    send_packet = (struct packet_header *)malloc(packet_len);
                    memset(send_packet, 0, packet_len);
                
                    send_packet->pack_length = packet_len;
                    send_packet->ph_type     = PT_LINKPACKET;
                    send_packet->ph_length     = ret;
                    send_packet->ph_num      = num++;
                    memcpy(send_packet->ph_data, rcv_buf, ret);
                
                    ret = send(g_connectionFD, send_packet, packet_len, 0);
                    if (ret == packet_len)        
                        PRINTF("%d &&send&&  %d bytes...... \n", send_packet->ph_num, ret);
                
                    free(send_packet);
                    send_packet = NULL;
                    
                }
            }
        }
    
    //free buffer
    free(ring_buf);    
    free(read_buf);
    ring_buf = NULL;
    read_buf = NULL;

    return 0;
}


/* 
 * linktunnel -s eth0 :2468
 * linktunnel -c eth0 192.168.229.3:2468
 */
int main(int argc, char* argv[])
{
    // char errbuf[PCAP_ERRBUF_SIZE] = {0};
    char* mode         = NULL;
    char* ifname     = NULL;
    char* ip         = NULL;
    char* port         = NULL;
    int      ret        = 0;
    struct sockaddr_ll sll;
    
    mode     = argv[1];
    ifname     = argv[2];
    ip         = argv[3];
    port     = strchr(ip, ':');

    if (argc != 4) {
        printf("opt error!\n");
        return -1;
    }
    
    memcpy(g_ethname, argv[2], strlen(argv[2]));
    printf("%s \n", g_ethname);
    
    if (port) {
        *port = '\0';
        port++;
    }
    else
        ;
    FPRINTF(stdout, "mode = %s, ifname = %s, ipaddr = %s, ipport = %s\n", mode, ifname, ip, port);

    if ((g_captureFD = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) < 0) {
        PRINTF("%d create packet error!\n", __LINE__);
        return -1;
    }
    
    memset(&ifr, 0, sizeof(ifr));
    strcpy(ifr.ifr_name, argv[2]);
    
    if ((ret = ioctl(g_captureFD, SIOCGIFFLAGS, &ifr)) < 0) {
        PRINTF("%d ioctl error !", __LINE__);
        close(g_captureFD);
        return -1;
    }
    
    
    memset(&sll, 0, sizeof(sll));
    sll.sll_family = AF_PACKET;
    sll.sll_ifindex = getIfaceIndex(g_captureFD, argv[2]);
    sll.sll_protocol = htons(ETH_P_ALL);
     
    //bind
    if (bind(g_captureFD, (struct sockaddr *)(&sll), sizeof(sll)) < 0) {
        PRINTF("%d bind error! \n", __LINE__);
        close(g_captureFD);
        return -1;
    }

    setPromisc(g_captureFD, 1);

	//Create Server
    if (!strcmp(mode, "-s")) {
        struct sockaddr_in servaddr, cliaddr;
        u_short servport = atoi(port);
        struct rlimit rt;

        #if 0
        /*set MAX number */
        rt.rlim_max = rt.rlim_cur = MAXEPOLLSIZE;
        if (setrlimit(RLIMIT_NOFILE, &rt) == -1) 
        {
            PRINTF("setrlimit error");
            return -1;
        }
        #endif
        
        int listenfd = socket(AF_INET, SOCK_STREAM, 0);
        if (listenfd < 0)
            PRINTF("create listen socket error! \n");

        bzero(&servaddr, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
        servaddr.sin_port = htons(servport);

        if (bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
            close(listenfd);
            PRINTF("bind listen socket error! \n");
        }

        if (listen(listenfd, 2) < 0) {
            close(listenfd);
            PRINTF("listen error! \n");
        }

        
        while (1) {
            socklen_t cliaddr_len = sizeof(cliaddr);
            g_connectionFD = accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len);
            printf("accept: %d\n", g_connectionFD);

            if (g_connectionFD >= 0) {
                dealReceiveData(doCommandServer, doRequestServer);
            }
        }

		close(listenfd);
    }

	//Create Client
    else if (!strcmp(mode, "-c")) {
        struct sockaddr_in servaddr;
        u_short servport = atoi(port);

        g_connectionFD = socket(AF_INET, SOCK_STREAM, 0);

        bzero(&servaddr, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_addr.s_addr =  inet_addr(ip);
        servaddr.sin_port = htons(servport);
    
        if (connect(g_connectionFD, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
            close(g_connectionFD);
            PRINTF("connect error !\n");
        }

        dealReceiveData(doCommandClient, doRequestClient);
        
        close(g_captureFD);
        PRINTF("quit.....\n");
    }

	close(g_captureFD);
    return 0;
}

